# -*- coding: utf-8 -*-
import time

import uvicorn
from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError, HTTPException
from fastapi.staticfiles import StaticFiles
from fastapi.responses import PlainTextResponse
from path import Path
from fastapi.middleware.cors import CORSMiddleware

from tutorial import app03, app04, app05, app06, app07, app08

app = FastAPI(
    title='FastAPI',
    version='1.0.0',
    docs_url='/docs',
    redoc_url='/redoc',
)

# 静态文件挂载
if not Path('./static').exists():
    Path('./static').makedirs()
app.mount('/static', StaticFiles(directory='./static'), name='static')


# 重写 HTTPException 异常处理
@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
    """
    :param request: 这个参数是必须的
    :param exc:
    :return:
    """
    return PlainTextResponse(str(exc.detail), status_code=exc.status_code)


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    """
    :param request: 这个参数是必须的
    :param exc:
    :return:
    """
    return PlainTextResponse(str(exc), status_code=400)


@app.middleware('http')
async def add_process_time_header(request: Request, call_next):  # call_next将接收request请求做为参数
    """ 添加请求处理时间中间件 """
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers['X-Process-Time'] = str(process_time)  # 添加自定义的以“X-”开头的请求头
    return response


app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://127.0.0.1",
        "http://127.0.0.1:8080"
    ],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(app03, prefix='/study03', tags=['第三章 请求参数和验证'])
app.include_router(app04, prefix='/study04', tags=['第四章 响应处理和FastAPI配置'])
app.include_router(app05, prefix='/study05', tags=['第五章 FastAPI的依赖注入系统'])
app.include_router(app06, prefix='/study06', tags=['第六章 安全、认证和授权'])
app.include_router(app07, prefix='/study07', tags=['第七章 FastAPI的数据库操作和多应用的目录结构设计'])
app.include_router(app08, prefix='/study08', tags=['第八章 中间件、CORS、后台任务、测试用例'])

if __name__ == '__main__':
    uvicorn.run(app=f'{Path(__file__).stem}:app', host='127.0.0.1', port=8000, reload=True, debug=True, workers=4)
